/*
 * Communication.cpp
 *
 *  Created on: Aug 27, 2011
 *      Author: ryan
 */

#include "Communication.h"
#include "mpi.h"
#include <iostream>
using namespace std;

#define COMM 12345

void Communication::initialize(int argc, char *argv[]) {
	if (!hasInitlized) {
		MPI::Init(argc, argv);
		SIZE = MPI::COMM_WORLD.Get_size();
		RANK = MPI::COMM_WORLD.Get_rank();
		hasInitlized = 1;
	}
}

void Communication::finalize() {
	if (hasInitlized) {
		MPI::Finalize();
	}
}

void Communication::sendTo(void *p, int size, int dst) {
	MPI_Isend(p, size, MPI_BYTE, dst, COMM, MPI::COMM_WORLD, &request);
}

void Communication::recvFrom(void *p, int size, int src) {
	MPI_Recv(p, size, MPI_BYTE, src, COMM, MPI::COMM_WORLD, &status);
}

void Communication::sendToNext(void* p, int size) {
	if (!mpiCheck() || next >= SIZE) {
		return;
	}
	MPI_Isend(p, size, MPI_BYTE, next, COMM, MPI::COMM_WORLD, &request);
}

void Communication::sendToPre(void* p, int size) {
	if (!mpiCheck() || pre < 0) {
		return;
	}
	MPI_Isend(p, size, MPI_BYTE, pre, COMM, MPI::COMM_WORLD, &request);
}

void Communication::recvFromNext(void* p, int size) {
	if (!mpiCheck() || next >= SIZE) {
		return;
	}
	MPI_Recv(p, size, MPI_BYTE, next, COMM, MPI::COMM_WORLD, &status);
}

void Communication::recvFromPre(void* p, int size) {
	if (!mpiCheck() || pre < 0) {
		return;
	}
	MPI_Recv(p, size, MPI_BYTE, pre, COMM, MPI::COMM_WORLD, &status);
}

bool Communication::mpiCheck() {
	if (!hasInitlized) {
		cout << "The Communication has not been initialized!" << endl;
	}
	return hasInitlized;
}

bool Communication::hasInitlized = 0;
int Communication::RANK = 0;
int Communication::SIZE = 0;
MPI_Request Communication::request;
MPI_Status Communication::status;
